#include "StrategyTree.h"

#include "StockNamespace.h"
#include "StockTypes.h"

#include "StrategyNode.h"
#include "MaxProfitVisitor.h"
#include "InitState.h"
#include "HoldState.h"
#include "CooldownState.h"


USING_STOCK_NS
using namespace std;

StrategyTree::StrategyTree()
{

}

StrategyTree::~StrategyTree()
{

}

void StrategyTree::Build(vector<StockPrice> prices)
{
	if (prices.empty())
	{
		return;
	}

	vector<StrategyNode *> newLeafNodes;
	newLeafNodes.push_back(&_root);

	for (vector<StockPrice>::const_iterator it = prices.begin(); it != prices.end(); it++)
	{
		StockPrice curPrice = (*it);

		vector<StrategyNode *> leafNodes = newLeafNodes;
		newLeafNodes.clear();

		for (vector<StrategyNode *>::const_iterator it = leafNodes.begin(); it != leafNodes.end(); it++)
		{
			StrategyNode *node = (*it);
			vector<StrategyNode *> children = node->DoAvailableTransactions(curPrice);
			node->AddChildrenNodes(children);

			newLeafNodes.insert(newLeafNodes.end(), children.begin(), children.end());
		}
		
	}
    
	return ;
}

StrategyNode * StrategyTree::GetMaxProfitNode()
{
	MaxProfitVisitor visitor(_root.GetProfit(), &_root);

	vector<StrategyNode *> children = _root.GetChildren();
	for (vector<StrategyNode *>::const_iterator it = children.begin(); it != children.end(); it++)
	{
		StrategyNode * node = (*it);
		node->Accept(&visitor);
	}

	return visitor.GetStrategyNode();
}

vector<StrategyNode *> StrategyTree::GetNodePath(StrategyNode * node)
{
	vector<StrategyNode *> path;

	if (node != NULL)
	{
		path.push_back(node);

		StrategyNode * parent = node->GetParent();
		while ((parent != NULL) && (parent != &_root))
		{
			path.push_back(parent);
			parent = parent->GetParent();
		}
	}

	return path;
}

